home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / ace_gpl_release / src_ansi / ace / c / declare.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-05  |  20.4 KB  |  979 lines

  1. /* << ACE >>
  2.  
  3.    -- Amiga BASIC Compiler --
  4.  
  5.    ** Parser: variable, structure, constant and external object 
  6.    ** declaration/definition code **
  7.    ** Copyright (C) 1998 David Benn
  8.    ** 
  9.    ** This program is free software; you can redistribute it and/or
  10.    ** modify it under the terms of the GNU General Public License
  11.    ** as published by the Free Software Foundation; either version 2
  12.    ** of the License, or (at your option) any later version.
  13.    **
  14.    ** This program is distributed in the hope that it will be useful,
  15.    ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.    ** GNU General Public License for more details.
  18.    **
  19.    ** You should have received a copy of the GNU General Public License
  20.    ** along with this program; if not, write to the Free Software
  21.    ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  22.  
  23.    Author: David J Benn
  24.    Date: 26th October-30th November, 1st-13th December 1991,
  25.    14th,20th-27th January 1992, 
  26.    2nd-17th, 21st-29th February 1992, 
  27.    1st,13th,14th,22nd,23rd March 1992,
  28.    21st,22nd April 1992,
  29.    2nd,3rd,11th,15th,16th May 1992,
  30.    7th,8th,9th,11th,13th,14th,28th,29th,30th June 1992,
  31.    2nd-8th,14th-19th,26th-29th July 1992,
  32.    1st-3rd,7th,8th,9th August 1992,
  33.    6th,7th December 1992,
  34.    14th February 1993,
  35.    12th,16th April 1993,
  36.    20th,30th June 1993,
  37.    15th December 1993,
  38.    2nd January 1994,
  39.    26th February 1994,
  40.    12th June 1994,
  41.    8th,9th September 1994,
  42.    1st,2nd October 1994,
  43.    11th,22nd June 1996
  44.  */
  45.  
  46. #include "acedef.h"
  47. #include <string.h>
  48. #include <clib/mathffp_protos.h>
  49.  
  50. /* locals */
  51. static char *frame_ptr[] = {"(a4)", "(a5)"};
  52.  
  53. /* externals */
  54. extern int sym;
  55. extern int typ;
  56. extern int lev;
  57. extern long structcount;
  58. extern char id[MAXIDSIZE];
  59. extern char ut_id[MAXIDSIZE];
  60. extern SHORT shortval;
  61. extern LONG longval;
  62. extern float singleval;
  63. extern SYM *curr_item;
  64. extern SYM *structdef_item;
  65. extern STRUCM *curr_structmem;
  66. extern BOOL end_of_source;
  67. float smul = 1.0f;
  68.  
  69. /* functions */
  70. void define_structure (void)
  71. {
  72. /* define a structure data type */
  73.  
  74.   SHORT mem_count = 0;
  75.   SYM *structdef_item, *struct_mbr_def;
  76.   int mem_type;
  77.   int oldlevel;
  78.   int string_size;
  79.  
  80. /* define all structures 
  81.    at level ZERO */
  82.   oldlevel = lev;
  83.   lev = ZERO;
  84.  
  85.   insymbol ();
  86.   if (sym != ident)
  87.     _error (7);
  88.   else
  89.     {
  90.       if (exist (id, structdef))
  91.     _error (62);
  92.       else
  93.     {
  94.       /* create symbol table entry */
  95.       enter (id, notype, structdef, 0);
  96.       structdef_item = curr_item;
  97.  
  98.       /* get structure members */
  99.       insymbol ();
  100.       while (sym == endofline)
  101.         insymbol ();    /* skip blank line(s) */
  102.  
  103.       do
  104.         {
  105.           if ((sym != bytesym) && (sym != shortintsym) && (sym != addresssym) &&
  106.           (sym != longintsym) && (sym != singlesym) && (sym != stringsym) &&
  107.           (sym != ident))
  108.         {
  109.           _error (63);
  110.           insymbol ();
  111.         }
  112.           else
  113.         {
  114.           struct_mbr_def = NULL;
  115.  
  116.           /* type of member? */
  117.           switch (sym)
  118.             {
  119.             case bytesym:
  120.               mem_type = bytetype;
  121.               break;
  122.             case shortintsym:
  123.               mem_type = shorttype;
  124.               break;
  125.             case longintsym:
  126.               mem_type = longtype;
  127.               break;
  128.             case addresssym:
  129.               mem_type = longtype;
  130.               break;
  131.             case singlesym:
  132.               mem_type = singletype;
  133.               break;
  134.             case stringsym:
  135.               mem_type = stringtype;
  136.               break;
  137.             case ident:
  138.               mem_type = structure;
  139.               if (!exist (id, structdef) ||
  140.               strcmp (id, structdef_item->name) == 0)
  141.             {
  142.               _error (65);    /* unknown or current structdef */
  143.               mem_type = undefined;
  144.             }
  145.               else
  146.             /* structure definition */
  147.             struct_mbr_def = curr_item;
  148.               break;
  149.             }
  150.  
  151.           if (mem_type == undefined)
  152.             insymbol ();
  153.           else
  154.             {
  155.               insymbol ();
  156.               if (sym != ident)
  157.             {
  158.               _error (7);
  159.               insymbol ();
  160.             }
  161.               else
  162.             {
  163.               add_struct_member (structdef_item, id, mem_type, struct_mbr_def);
  164.               mem_count++;
  165.             }
  166.             }
  167.  
  168.           insymbol ();
  169.  
  170.           /* specify optional string size? */
  171.           if ((mem_type == stringtype) && (sym == sizesym))
  172.             {
  173.               insymbol ();
  174.               if (sym == shortconst)
  175.             string_size = (LONG) shortval;
  176.               else if (sym == longconst)
  177.             string_size = longval;
  178.               else if (sym == ident && exist (id, constant))
  179.             {
  180.               /* short or long defined constant? */
  181.               if (curr_item->type == shorttype)
  182.                 string_size = (LONG) curr_item->numconst.shortnum;
  183.               else if (curr_item->type == longtype)
  184.                 string_size = curr_item->numconst.longnum;
  185.               else
  186.                 _error (4);        /* needed a short or long constant */
  187.             }
  188.               else
  189.             _error (27);    /* numeric constant expected */
  190.  
  191.               if (string_size <= 0L)
  192.             _error (41);    /* non-positive string size! */
  193.  
  194.               insymbol ();
  195.  
  196.               /* change member and struct info */
  197.               curr_structmem->strsize = string_size;
  198.               structdef_item->size -= MAXSTRLEN;    /* subtract default string size */
  199.               structdef_item->size += string_size;
  200.             }
  201.         }
  202.           while (sym == endofline)
  203.         insymbol ();    /* skip blank line(s) */
  204.         }
  205.       while (sym != endsym && sym != structsym && !end_of_source);
  206.  
  207.       if (sym != endsym)
  208.         _error (64);
  209.       else
  210.         {
  211.           insymbol ();
  212.           if (sym != structsym)
  213.         _error (64);
  214.           else
  215.         insymbol ();
  216.         }
  217.  
  218.       /* don't want to free memory if no member list! */
  219.       if (mem_count == 0)
  220.         structdef_item->object = undefined;
  221.     }
  222.     }
  223.   lev = oldlevel;        /* restore level */
  224. }
  225.  
  226. void declare_structure (void)
  227. {
  228. /* declare one or more instances
  229.    of a structure (at level ZERO).
  230.  
  231.    syntax: DECLARE STRUCT <struct-type> [*] <ident> [,[*] <ident>..]
  232.  
  233.  */
  234.   STRUCM *curr_member;
  235.   BOOL struct_pointer = FALSE;
  236.   char addrbuf[40], numbuf[40];
  237.   char structname[80], structlabel[80];
  238.   char strsize[20], bss_spec[40];
  239.  
  240.   insymbol ();
  241.  
  242.   if (sym != ident)
  243.     {
  244.       _error (7);
  245.       insymbol ();
  246.     }
  247.   else
  248.     {
  249.       if (!exist (id, structdef))
  250.     {
  251.       _error (65);
  252.       insymbol ();
  253.     }            /* unknown structdef */
  254.       else
  255.     {
  256.       structdef_item = curr_item;    /* pointer to structdef info */
  257.  
  258.       do
  259.         {
  260.           insymbol ();
  261.           if (sym == multiply)
  262.         {
  263.           struct_pointer = TRUE;
  264.           insymbol ();
  265.         }
  266.  
  267.           if (sym != ident)
  268.         _error (7);
  269.           else
  270.         {
  271.           if (exist (id, structure))
  272.             _error (66);
  273.           else
  274.             {
  275.               /* enter instance of structure in
  276.                  symbol table and get stack frame
  277.                  address.
  278.                */
  279.               enter (id, notype, structure, 0);
  280.               curr_item->other = structdef_item;    /* ptr to structdef node in symtab */
  281.  
  282.               itoa (-1 * curr_item->address, addrbuf, 10);
  283.               strcat (addrbuf, frame_ptr[lev]);
  284.  
  285.               /* if a pointer to a structure
  286.                  make it NULL otherwise create 
  287.                  a BSS object.
  288.                */
  289.               if (struct_pointer)
  290.             gen ("move.l", "#0", addrbuf);    /* pointer to structure */
  291.               else
  292.             {
  293.               /* BSS structure name */
  294.               strcpy (structname, "_structure");
  295.               itoa (structcount++, numbuf, 10);
  296.               strcat (structname, numbuf);
  297.  
  298.               /* BSS structure label */
  299.               strcpy (structlabel, structname);
  300.               strcat (structlabel, ":\0");
  301.  
  302.               /* create BSS object - long word aligned! */
  303.               enter_BSS ("  ", "CNOP 0,4");
  304.               enter_BSS (structlabel, "  ");
  305.  
  306.               curr_member = structdef_item->structmem->next;    /* head has no mbr data */
  307.               while (curr_member != NULL)
  308.                 {
  309.                   switch (curr_member->type)
  310.                 {
  311.                 case bytetype:
  312.                   enter_BSS ("  ", "ds.b 1");
  313.                   break;
  314.                 case shorttype:
  315.                   enter_BSS ("  ", "ds.w 1");
  316.                   break;
  317.                 case longtype:
  318.                   enter_BSS ("  ", "ds.l 1");
  319.                   break;
  320.                 case singletype:
  321.                   enter_BSS ("  ", "ds.l 1");
  322.                   break;
  323.  
  324.                 case stringtype:
  325.                 case structure:
  326.                   ltoa (curr_member->strsize, strsize, 10);
  327.                   strcpy (bss_spec, "ds.b ");
  328.                   strcat (bss_spec, strsize);
  329.                   enter_BSS ("  ", bss_spec);
  330.                   break;
  331.                 }
  332.                   curr_member = curr_member->next;
  333.                 }
  334.  
  335.               enter_BSS ("  ", "  ");    /* place a space before next BSS object! */
  336.  
  337.               /* store address of BSS object 
  338.                  in stack frame.
  339.                */
  340.               gen ("pea", structname, "  ");
  341.               gen ("move.l", "(sp)+", addrbuf);
  342.             }
  343.             }
  344.         }
  345.           insymbol ();
  346.         }
  347.       while (sym == comma);
  348.     }
  349.     }
  350. }
  351.  
  352. void define_constant (void)
  353. {
  354. /* define a NUMERIC constant 
  355.    syntax: CONST <ident>=[-|+]<numconst>[,..] 
  356.  */
  357.   char const_id[MAXIDSIZE];
  358.   BOOL numconstant;
  359.   int consttyp;
  360.   SHORT shortc;
  361.   LONG longc;
  362.   float singlec;
  363.   BOOL negate;
  364.   int oldlevel;
  365.  
  366.   /* define all constants 
  367.      at level ZERO */
  368.   oldlevel = lev;
  369.   lev = ZERO;
  370.  
  371.   do
  372.     {
  373.       numconstant = FALSE;
  374.       negate = FALSE;
  375.  
  376.       insymbol ();
  377.       if (sym != ident)
  378.     _error (7);
  379.       else
  380.     {
  381.       strcpy (const_id, id);    /* save name */
  382.       insymbol ();
  383.       if (sym != equal)
  384.         _error (5);
  385.       else
  386.         {
  387.           insymbol ();
  388.           if (exist (const_id, constant))    /* don't try to reassign it! */
  389.         _error (53);
  390.           else
  391.         {
  392.           /* unary minus or plus? (optional) */
  393.           if ((sym == minus) || (sym == plus))
  394.             {
  395.               switch (sym)
  396.             {
  397.             case minus:
  398.               negate = TRUE;
  399.               break;
  400.             case plus:
  401.               negate = FALSE;
  402.               break;
  403.             }
  404.               insymbol ();
  405.             }
  406.  
  407.           /* literal constant? */
  408.           if ((sym == shortconst) || (sym == longconst) || (sym == singleconst))
  409.             {
  410.               numconstant = TRUE;
  411.               consttyp = typ;
  412.               switch (consttyp)
  413.             {
  414.             case shorttype:
  415.               shortc = shortval;
  416.               break;
  417.             case longtype:
  418.               longc = longval;
  419.               break;
  420.             case singletype:
  421.               singlec = singleval;
  422.               break;
  423.             }
  424.             }
  425.           else
  426.             /* defined constant? */
  427.           if ((sym == ident) && (exist (id, constant)))
  428.             {
  429.               consttyp = curr_item->type;
  430.               if (consttyp != stringtype)
  431.             {
  432.               numconstant = TRUE;
  433.               switch (consttyp)
  434.                 {
  435.                 case shorttype:
  436.                   shortc = curr_item->numconst.shortnum;
  437.                   break;
  438.                 case longtype:
  439.                   longc = curr_item->numconst.longnum;
  440.                   break;
  441.                 case singletype:
  442.                   singlec = curr_item->numconst.singlenum;
  443.                   break;
  444.                 }
  445.             }
  446.               else
  447.             _error (27);
  448.             }
  449.           else
  450.             _error (27);
  451.         }
  452.  
  453.           /* create a new numeric constant? */
  454.           if (numconstant)
  455.         {
  456.           switch (consttyp)
  457.             {
  458.             case shorttype:
  459.               enter(const_id, shorttype, constant, 0);
  460.               if (negate)
  461.             shortc *= -1;
  462.               curr_item->numconst.shortnum = shortc;
  463.               break;
  464.  
  465.             case longtype:
  466.               enter(const_id, longtype, constant, 0);
  467.               if (negate)
  468.             longc *= -1;
  469.               curr_item->numconst.longnum = longc;
  470.               break;
  471.  
  472.             case singletype:
  473.               enter(const_id, singletype, constant, 0);
  474.               if (negate)
  475.             singlec = SPMul(singlec, smul);
  476.               curr_item->numconst.singlenum = singlec;
  477.               break;
  478.             }
  479.           insymbol ();
  480.         }
  481.         }
  482.     }
  483.     }
  484.   while (sym == comma);
  485.  
  486.   /* restore level */
  487.   lev = oldlevel;
  488. }
  489.  
  490. void declare_variable (int vartype)
  491. {
  492. /* declare a variable 
  493.    and initialise it. 
  494.  */
  495.   char addrbuf[40];
  496.   LONG string_size = MAXSTRLEN;
  497.   BOOL normal_string_variable = TRUE;
  498.   SYM *str_item;
  499.  
  500.   do
  501.     {
  502.       insymbol ();
  503.       if (sym != ident)
  504.     _error (7);
  505.       else
  506.     {
  507.       if (exist (id, variable))
  508.         {
  509.           _error (54);
  510.           insymbol ();
  511.         }
  512.       else
  513.         {
  514.           enter (id, vartype, variable, 0);
  515.  
  516.           itoa (-1 * curr_item->address, addrbuf, 10);
  517.           strcat (addrbuf, frame_ptr[lev]);
  518.  
  519.           insymbol ();
  520.  
  521.           switch (vartype)
  522.         {
  523.         case shorttype:
  524.           gen ("move.w", "#0", addrbuf);
  525.           break;
  526.  
  527.         case longtype:
  528.           gen ("move.l", "#0", addrbuf);
  529.           break;
  530.  
  531.         case singletype:
  532.           gen ("move.l", "#0", addrbuf);
  533.           break;
  534.  
  535.         case stringtype:
  536.           str_item = curr_item;
  537.           if (sym == addresssym)
  538.             {
  539.               normal_string_variable = FALSE;
  540.               /* don't want to create a BSS object! */
  541.               str_item->new_string_var = FALSE;
  542.  
  543.               insymbol ();
  544.               if (expr () != longtype)
  545.             _error (4);
  546.               else
  547.             /* store address of string in stack frame */
  548.             gen ("move.l", "(sp)+", addrbuf);
  549.             }
  550.           else if (sym == sizesym)
  551.             {
  552.               insymbol ();
  553.               if (sym == shortconst)
  554.             string_size = (LONG) shortval;
  555.               else if (sym == longconst)
  556.             string_size = longval;
  557.               else if (sym == ident && exist (id, constant))
  558.             {
  559.               if (curr_item->type == shorttype)
  560.                 string_size = (LONG) curr_item->numconst.shortnum;
  561.               else if (curr_item->type == longtype)
  562.                 string_size = curr_item->numconst.longnum;
  563.               else
  564.                 _error (4);
  565.             }
  566.               else if (sym == singleconst)
  567.             _error (4);
  568.               else
  569.             _error (27);    /* numeric constant expected */
  570.  
  571.               if (string_size <= 0L)
  572.             _error (41);    /* not positive! */
  573.  
  574.               insymbol ();
  575.             }
  576.  
  577.           if (normal_string_variable)
  578.             {
  579.               /* initialise with the NULL string */
  580.               enter_DATA ("_nullstring:", "dc.b 0");
  581.               gen ("pea", "_nullstring", "  ");
  582.               assign_to_string_variable (str_item, string_size);
  583.             }
  584.  
  585.           str_item->decl = declared;
  586.           str_item->size = string_size;
  587.  
  588.           break;
  589.         }
  590.         }
  591.     }
  592.     }
  593.   while (sym == comma);
  594. }
  595.  
  596. void define_external_object (void)
  597. {
  598.   /* declare an external 
  599.      function or variable 
  600.    */
  601.  
  602.   insymbol ();
  603.   if (sym == functionsym)
  604.     define_external_function ();
  605.   else
  606.     define_external_variable ();
  607. }
  608.  
  609. void define_external_variable (void)
  610. {
  611. /* declare an external variable */
  612.   char buf[MAXIDSIZE], extvarid[MAXIDSIZE + 1];
  613.   int oldlevel;
  614.   int vartype = undefined;
  615.  
  616.   /* all external variables are at level ZERO */
  617.   oldlevel = lev;
  618.   lev = ZERO;
  619.  
  620.   /* type identifiers */
  621.   if (sym == shortintsym || sym == longintsym || sym == addresssym ||
  622.       sym == singlesym || sym == stringsym)
  623.     {
  624.       switch (sym)
  625.     {
  626.     case shortintsym:
  627.       vartype = shorttype;
  628.       break;
  629.     case longintsym:
  630.       vartype = longtype;
  631.       break;
  632.     case addresssym:
  633.       vartype = longtype;
  634.       break;
  635.     case singlesym:
  636.       vartype = singletype;
  637.       break;
  638.     case stringsym:
  639.       vartype = stringtype;
  640.       break;
  641.     }
  642.       insymbol ();
  643.     }
  644.  
  645.   /* get the variable's name */
  646.   if (sym != ident)
  647.     _error (7);
  648.   {
  649.     /* 
  650.        ** Add an underscore prefix 
  651.        ** if one is not present.
  652.      */
  653.     strcpy (buf, ut_id);
  654.     remove_qualifier (buf);
  655.     if (buf[0] != '_')
  656.       {
  657.     strcpy (extvarid, "_\0");
  658.     strcat (extvarid, buf);
  659.       }
  660.     else
  661.       strcpy (extvarid, buf);
  662.  
  663.     /* enter variable into symbol table */
  664.     if (vartype == undefined)
  665.       vartype = typ;
  666.     if (exist (extvarid, extvar))
  667.       _error (54);        /* variable exists */
  668.     else
  669.       {
  670.     enter (extvarid, vartype, extvar, 0);
  671.  
  672.     /* make an external reference to it */
  673.     enter_XREF (extvarid);
  674.       }
  675.  
  676.     insymbol ();
  677.   }
  678.  
  679.   lev = oldlevel;
  680. }
  681.  
  682. void define_external_function (void)
  683. {
  684. /* declare an external function */
  685.   char buf[MAXIDSIZE], extfuncid[MAXIDSIZE + 1];
  686.   int oldlevel;
  687.   int functype = undefined;
  688.  
  689.   /* all external functions are at level ZERO */
  690.   oldlevel = lev;
  691.   lev = ZERO;
  692.  
  693.   insymbol ();
  694.  
  695.   /* type identifiers */
  696.   if (sym == shortintsym || sym == longintsym || sym == addresssym ||
  697.       sym == singlesym || sym == stringsym)
  698.     {
  699.       switch (sym)
  700.     {
  701.     case shortintsym:
  702.       functype = shorttype;
  703.       break;
  704.     case longintsym:
  705.       functype = longtype;
  706.       break;
  707.     case addresssym:
  708.       functype = longtype;
  709.       break;
  710.     case singlesym:
  711.       functype = singletype;
  712.       break;
  713.     case stringsym:
  714.       functype = stringtype;
  715.       break;
  716.     }
  717.       insymbol ();
  718.     }
  719.  
  720.   /* get the function's name */
  721.   if (sym != ident)
  722.     _error (7);
  723.   {
  724.     /* add an underscore prefix 
  725.        if one is not present 
  726.      */
  727.     strcpy (buf, ut_id);
  728.     remove_qualifier (buf);
  729.     if (buf[0] != '_')
  730.       {
  731.     strcpy (extfuncid, "_\0");
  732.     strcat (extfuncid, buf);
  733.       }
  734.     else
  735.       strcpy (extfuncid, buf);
  736.  
  737.     /* enter function into symbol table */
  738.     if (functype == undefined)
  739.       functype = typ;
  740.     if (exist (extfuncid, extfunc))
  741.       _error (33);        /* duplicate function name */
  742.     else
  743.       {
  744.     enter (extfuncid, functype, extfunc, 0);
  745.  
  746.     /* make an external reference to it */
  747.     enter_XREF (extfuncid);
  748.       }
  749.  
  750.     insymbol ();
  751.   }
  752.  
  753.   lev = oldlevel;
  754. }
  755.  
  756. void call_external_function (char *extfuncid, BOOL * need_symbol)
  757. {
  758. /* CALL an external function -- level ZERO */
  759.   SYM *extfunc_item;
  760.   int i;
  761.   long popcount = 0;
  762.   char buf[40], numbuf[40];
  763.  
  764.   if (exist (extfuncid, extfunc))    /* preserve case */
  765.     {
  766.       /* save registers */
  767.       gen ("movem.l", "d1-d7/a0-a6", "-(sp)");
  768.  
  769.       extfunc_item = curr_item;
  770.       /* insymbol() is called before entry to this function */
  771.       if (sym == lparen)
  772.     {
  773.       load_mc_params (extfunc_item);
  774.       *need_symbol = TRUE;
  775.     }
  776.       else
  777.     {
  778.       extfunc_item->no_of_params = 0;
  779.       *need_symbol = FALSE;
  780.     }
  781.  
  782.       /* call routine */
  783.       gen ("jsr", extfunc_item->name, "  ");
  784.  
  785.       /* pop parameters? */
  786.       if (extfunc_item->no_of_params != 0)
  787.     {
  788.       popcount = 0;
  789.       for (i = 0; i < extfunc_item->no_of_params; i++)
  790.         {
  791.           if (extfunc_item->p_type[i] == shorttype)
  792.         popcount += 2;
  793.           else
  794.         popcount += 4;
  795.         }
  796.       /* add popcount to sp */
  797.       strcpy (buf, "#\0");
  798.       itoa (popcount, numbuf, 10);
  799.       strcat (buf, numbuf);
  800.       gen ("add.l", buf, "sp");
  801.     }
  802.  
  803.       /* restore registers */
  804.       gen ("movem.l", "(sp)+", "d1-d7/a0-a6");
  805.     }
  806. }
  807.  
  808. void define_common_or_global_variable (int varsym)
  809. {
  810. /*
  811.    ** Declare a common or global variable.
  812.    ** Treated internally as an external variable.
  813.  */
  814.   char buf[MAXIDSIZE];
  815.   char extvarid[MAXIDSIZE + 2], extvarlabel[MAXIDSIZE + 3];
  816.   int oldlevel;
  817.   int vartype = undefined;
  818.   SYM *str_item=curr_item;
  819.   LONG string_size = MAXSTRLEN;
  820.   BOOL normal_string_variable = TRUE;
  821.   char bss_size[20];
  822.  
  823.   insymbol ();
  824.  
  825.   /* all common variables are at level ZERO */
  826.   oldlevel = lev;
  827.   lev = ZERO;
  828.  
  829.   /* optional type identifiers */
  830.   if (sym == shortintsym || sym == longintsym || sym == addresssym ||
  831.       sym == singlesym || sym == stringsym)
  832.     {
  833.       switch (sym)
  834.     {
  835.     case shortintsym:
  836.       vartype = shorttype;
  837.       break;
  838.     case longintsym:
  839.       vartype = longtype;
  840.       break;
  841.     case addresssym:
  842.       vartype = longtype;
  843.       break;
  844.     case singlesym:
  845.       vartype = singletype;
  846.       break;
  847.     case stringsym:
  848.       vartype = stringtype;
  849.       break;
  850.     }
  851.  
  852.       insymbol ();
  853.     }
  854.  
  855.   /* get the variable's name */
  856.   if (sym != ident)
  857.     _error (7);
  858.   {
  859.     /* 
  860.        ** Add an underscore prefix 
  861.        ** if one is not present.
  862.      */
  863.     strcpy (buf, ut_id);
  864.     remove_qualifier (buf);
  865.     if (buf[0] != '_')
  866.       {
  867.     sprintf (extvarid, "_%s", buf);
  868.       }
  869.     else
  870.       strcpy (extvarid, buf);
  871.  
  872.     /* enter variable into symbol table */
  873.     if (vartype == undefined)
  874.       vartype = typ;
  875.     if (exist (extvarid, extvar))
  876.       _error (54);        /* variable exists  */
  877.     else
  878.       {
  879.     enter (extvarid, vartype, extvar, 0);
  880.  
  881.     /* 
  882.        ** Make an appropriate BSS object.
  883.      */
  884.     sprintf (extvarlabel, "%s:", extvarid);
  885.     switch (vartype)
  886.       {
  887.       case shorttype:
  888.         enter_BSS (extvarlabel, "ds.w 1");
  889.         gen ("move.w", "#0", extvarid);
  890.         insymbol ();
  891.         break;
  892.  
  893.       case longtype:
  894.         enter_BSS (extvarlabel, "ds.l 1");
  895.         gen ("move.l", "#0", extvarid);
  896.         insymbol ();
  897.         break;
  898.  
  899.       case singletype:
  900.         enter_BSS (extvarlabel, "ds.l 1");
  901.         gen ("move.l", "#0", extvarid);
  902.         insymbol ();
  903.         break;
  904.  
  905.       case stringtype:
  906.         insymbol ();
  907.         if (sym == sizesym)
  908.           {
  909.         insymbol ();
  910.  
  911.         /* create own BSS object */
  912.         str_item->new_string_var = FALSE;
  913.  
  914.         if (sym == shortconst)
  915.           string_size = (LONG) shortval;
  916.         else if (sym == longconst)
  917.           string_size = longval;
  918.         else if (sym == ident && exist (id, constant))
  919.           {
  920.             if (curr_item->type == shorttype)
  921.               string_size = (LONG) curr_item->numconst.shortnum;
  922.             else if (curr_item->type == longtype)
  923.               string_size = curr_item->numconst.longnum;
  924.             else
  925.               _error (4);
  926.           }
  927.         else if (sym == singleconst)
  928.           _error (4);
  929.         else
  930.           _error (27);    /* numeric constant expected */
  931.  
  932.         if (string_size <= 0L)
  933.           _error (41);    /* not positive! */
  934.  
  935.         insymbol ();
  936.           }
  937.  
  938.         str_item->decl = declared;
  939.         str_item->size = string_size;
  940.  
  941.         /*
  942.            ** Create BSS object.
  943.          */
  944.         sprintf (bss_size, "ds.l %d", string_size);
  945.         enter_BSS (extvarlabel, bss_size);
  946.  
  947.         if (normal_string_variable)
  948.           {
  949.         /* initialise with the NULL string */
  950.         enter_DATA ("_nullstring:", "dc.b 0");
  951.         gen ("lea", extvarid, "a0");
  952.         gen ("lea", "_nullstring", "a1");
  953.         gen ("jsr", "_strcpy", "  ");
  954.         enter_XREF ("_strcpy");
  955.           }
  956.  
  957.         break;
  958.       }
  959.  
  960.     /*
  961.        ** Only make it externally referenceable if it's a COMMON variable
  962.        ** not a GLOBAL variable.
  963.      */
  964.     if (varsym == commonsym)
  965.       {
  966.         /* 
  967.            ** Make it externally referenceable.
  968.            ** The '*' is used by enter_XREF() 
  969.            ** to make this an XDEF.
  970.          */
  971.         extvarid[0] = '*';
  972.         enter_XREF (extvarid);
  973.       }
  974.       }
  975.   }
  976.  
  977.   lev = oldlevel;
  978. }
  979.